package com.bibrApp.difu.actvity.connect_mvp;

import androidx.recyclerview.widget.RecyclerView;

import android.annotation.SuppressLint;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.bibrApp.difu.BeemIntent;
import com.bibrApp.difu.R;
import com.bibrApp.difu.actvity.u_account_mvp.UAccountActivity;
import com.bibrApp.difu.base.BaseActivity;
import com.bibrApp.difu.proto2javabean.FeatureBean;
import com.bibrApp.difu.utils.ClsPublicUtils;
import com.bibrApp.difu.utils.DialogUtils;
import com.bibrApp.difu.utils.IntentUtil;
import com.bibrApp.difu.utils.Protocol;
import com.bibrApp.difu.utils.ToastUtils;
import com.bibrApp.difu.utils.UIUtils;
import com.google.gson.Gson;
import com.google.protobuf.InvalidProtocolBufferException;
import com.googlecode.protobuf.format.JsonFormat;
import com.satoshilabs.trezor.lib.protobuf.TrezorMessageManagement;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import butterknife.BindView;
import butterknife.OnClick;

public class ConnectActivity extends BaseActivity<ConnectPresenter> implements IConnectView {


    @BindView(R.id.recycler_view)
    RecyclerView recyclerView;
    @BindView(R.id.tv_loading_info)
    TextView tvLoading;
    @BindView(R.id.pb_loading)
    ProgressBar pbLoading;
    @BindView(R.id.tv_device_info)
    TextView tvDeviceInfo;
    @BindView(R.id.line_device)
    View lineDevice;


    @BindView(R.id.ll_loading)
    LinearLayout llLoading;
    @BindView(R.id.ll_list)
    LinearLayout llList;
    @BindView(R.id.ll_backup)
    LinearLayout llBackup;
    @BindView(R.id.ll_backuping)
    LinearLayout llBackuping;
    @BindView(R.id.ll_backuped)
    LinearLayout llBackuped;
    @BindView(R.id.ll_ping_info)
    LinearLayout llPingInfo;

    @BindView(R.id.item_name)
    TextView tvUName;
    @BindView(R.id.ll_menu)
    LinearLayout llMenu;
    @BindView(R.id.item_connect)
    TextView tvConnect;
    @BindView(R.id.item_cancel)
    TextView tvCancel;


    private ConnectAdapter adapter;
    private UsbManager usbManager;
    private UsbDevice mUsbDevice;
    private UsbInterface mUsbInterface;
    private UsbDeviceConnection mUsbDeviceConnection;
    private UsbEndpoint usbEndpointIn;
    private UsbEndpoint usbEndpointOut;
    private Thread mReadingthread;

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 101) {
                showToast((String) msg.obj);
            }
        }
    };
    private Dialog dialog;
    private Context mContext;

    @Override
    protected void initPresenter() {
        presenter = new ConnectPresenter(this, this);
        presenter.init();
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_connect;
    }


    @Override
    public void error(String msg) {

    }

    @Override
    public void success(String msg) {

    }

    @Override
    public void initView() {
        mContext = this;
        IntentFilter filter = new IntentFilter(BeemIntent.ACTION_USB_INTENT);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        registerReceiver(mUsbReceiver, filter);

        onLoading();
        //handler.postDelayed(() -> checkUsb(), 1000);
    }

    @OnClick(R.id.tv_cancel)
    public void cancelClick() {
        showPingInfo();
    }

    @OnClick(R.id.return_iv)
    public void backClick() {
        finish();
    }

    private void onLoading() {
        llLoading.setVisibility(View.VISIBLE);
        llList.setVisibility(View.GONE);
        llBackup.setVisibility(View.GONE);
        llBackuping.setVisibility(View.GONE);
        llBackuped.setVisibility(View.GONE);
        llPingInfo.setVisibility(View.GONE);
        checkUsb();
    }

    private void showUsbItem(UsbDevice usbDevice) {
        llLoading.setVisibility(View.GONE);
        llList.setVisibility(View.VISIBLE);
        llBackup.setVisibility(View.GONE);
        llBackuping.setVisibility(View.GONE);
        llBackuped.setVisibility(View.GONE);
        llPingInfo.setVisibility(View.GONE);
        if (Build.VERSION.SDK_INT > 21) {
            tvUName.setText(usbDevice.getProductName());
        } else {
            tvUName.setText(usbDevice.getProductId());
        }


        tvUName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                llMenu.setVisibility(llMenu.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE);
            }
        });
        tvConnect.setOnClickListener(v -> {
            connectDevice(usbDevice);
//            checkUsb();

        });
        tvCancel.setOnClickListener(v -> {
            llMenu.setVisibility(View.GONE);
        });
    }

    private void showBackupTips() {
        llLoading.setVisibility(View.GONE);
        llList.setVisibility(View.GONE);
        llBackup.setVisibility(View.VISIBLE);
        llBackuping.setVisibility(View.GONE);
        llBackuped.setVisibility(View.GONE);
        llPingInfo.setVisibility(View.GONE);

        findViewById(R.id.tv_confirm).setOnClickListener(view -> {
            showBackuping();
        });
    }

    private void showBackuping() {
        llLoading.setVisibility(View.GONE);
        llList.setVisibility(View.GONE);
        llBackup.setVisibility(View.GONE);
        llBackuping.setVisibility(View.VISIBLE);
        llBackuped.setVisibility(View.GONE);
        llPingInfo.setVisibility(View.GONE);

    }

    private void showPingInfo() {
        llLoading.setVisibility(View.GONE);
        llList.setVisibility(View.GONE);
        llBackup.setVisibility(View.GONE);
        llBackuping.setVisibility(View.GONE);
        llBackuped.setVisibility(View.GONE);
        llPingInfo.setVisibility(View.VISIBLE);

        findViewById(R.id.tv_next2).setOnClickListener(view -> {

        });
    }


    private void connectDevice(UsbDevice item) {
        mUsbDevice = item;
        if (usbManager.hasPermission(mUsbDevice)) {
            findIntfAndEpt();
        } else {
            getUsbPermission(mUsbDevice);
        }
    }

    private void checkUsb() {
        usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
        if (usbManager == null) {
            return;
        }
        HashMap<String, UsbDevice> deviceHashMap = usbManager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceHashMap.values().iterator();
//        ArrayList<UsbDevice> usbDeviceList = new ArrayList<>();//存放usb数量
        while (deviceIterator.hasNext()) {
            UsbDevice device = deviceIterator.next();
            if (device.getVendorId() == 0x1209 && device.getProductId() == 0x53C1) {//找到我们的usb设备
                mUsbDevice = device;
//                usbDeviceList.add(device);
            }
        }
        if (mUsbDevice == null) {
            return;
        }
        showUsbItem(mUsbDevice);
        if (usbManager.hasPermission(mUsbDevice)) {
            findIntfAndEpt();
        } else {
            getUsbPermission(mUsbDevice);
        }
        /*if (usbDeviceList.size() > 0) {
            showUsbList(usbDeviceList);
        } else {
            showToast("没有找到USB设备");
//            finish();
        }*/
    }


    //开始申请USB权限
    private void getUsbPermission(UsbDevice mUSBDevice) {
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(BeemIntent.ACTION_USB_INTENT), 0);
        usbManager.requestPermission(mUSBDevice, pendingIntent); // 该代码执行后，系统弹出一个对话框/等待权限
    }

    /**
     * 寻找接口和分配结点
     */
    private void findIntfAndEpt() {
        if (mUsbDevice == null) {
            ToastUtils.ShowToast(this, "没有找到相匹配的设备");
            return;
        }
        if (mUsbDevice.getInterfaceCount() <= 0) {
            showToast("没有找到接口");
            return;
        }
        mUsbInterface = mUsbDevice.getInterface(0);
        //打开设备，获取UsbDeviceConnection对象，连接设备，用于后面的通讯
        UsbDeviceConnection usbDeviceConnection = usbManager.openDevice(mUsbDevice);
        if (usbDeviceConnection == null) {
            ToastUtils.ShowToast(this, "连接失败");
            return;
        }
        if (usbDeviceConnection.claimInterface(mUsbInterface, true)) {
            //找到接口
            mUsbDeviceConnection = usbDeviceConnection;
            //用于UsbDeviceConnection与UsbInterface进行端点设置和通讯
            getEndPoint(mUsbDeviceConnection, mUsbInterface);
//            adapter.changeLoading(-1);
//            showToast("设备已连接");
            initU();
//            startReading();
            //sendData();
            //showConfirmPop();
        } else {
            //断开连接
            usbDeviceConnection.close();
        }
    }

    /**
     * 和u盾进行init交互
     */
    private byte[] sendbytes;

    private void initU() {
        int ret = -100;
        TrezorMessageManagement.Initialize.Builder initBuild = TrezorMessageManagement.Initialize.newBuilder();
        TrezorMessageManagement.Initialize initialize = initBuild.build();//组装成对应的protobuf文件中的方法
        byte[] init = initialize.toByteArray();//转成16进制

        if (mUsbDeviceConnection == null) {
            ToastUtils.ShowToast(mContext, "没有建立连接");
            checkUsb();
            return;
        }
        //添加协议
        List<byte[]> bytes = Protocol.encode(0, init);
        // 1,发送准备命令
        //通过usb hid传输数据给u盾
        for (int i = 0; i < bytes.size(); i++) {
            sendbytes = bytes.get(i);
            ret = mUsbDeviceConnection.bulkTransfer(usbEndpointOut, sendbytes, sendbytes.length, 5000);
        }
        if (ret == 64) {
            getHidMsg();
        }

    }

    private FeatureBean featureBean;

    @SuppressLint("StaticFieldLeak")
    public void getHidMsg() {
        new AsyncTask<String, Integer, List<byte[]>>() {
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                //开始接受信息
                DialogUtils.showDialog(mContext);
            }

            @Override
            protected List<byte[]> doInBackground(String... params) {
                List<byte[]> byteRe = new ArrayList<>();
                try {
                    boolean isContinue = true;
                    while (isContinue) {
                        byte[] recByte = new byte[64];
                        mUsbDeviceConnection.bulkTransfer(usbEndpointIn, recByte, recByte.length, 10000);
                        byteRe.add(recByte);
                        if (Protocol.hasHead(recByte)) {
                            byteRe.add(recByte);
                        } else {
                            isContinue = false;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return byteRe;
            }

            @Override
            protected void onPostExecute(List<byte[]> bytes) {
                if (bytes == null || bytes.size() == 0) {
                    //接受信息失败
                    DialogUtils.dismissDialog();
                    return;
                }
                String decodeStr = Protocol.decode(bytes);
                try {
                    TrezorMessageManagement.Features features = TrezorMessageManagement.Features.parseFrom(ClsPublicUtils.hexToBytes(decodeStr));
//                    String asJson = JsonFormat.printToString(features);
//                    featureBean = new Gson().fromJson(asJson, FeatureBean.class);
                    if (features != null) {
                        app.setuAccountName(features.getLabel());
                        IntentUtil.toActivity(UAccountActivity.class, mContext);
                        finish();
                    } else {
                        ToastUtils.ShowToast(mContext, "初始化不成功，请重新连接");
                    }
                } catch (InvalidProtocolBufferException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                DialogUtils.dismissDialog();
            }

        }.execute();
    }

    boolean isReading = false;

    //开线程读取数据
    private void startReading() {
        isReading = true;
        mReadingthread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (isReading && mUsbDeviceConnection != null) {
                    synchronized (this) {
                        byte[] bytes = new byte[usbEndpointIn.getMaxPacketSize()];
                        int ret = mUsbDeviceConnection.bulkTransfer(usbEndpointIn, bytes, bytes.length, 100);

                        if (ret > 0) {
                            Message message = new Message();
                            message.what = 101;
                            message.obj = ClsPublicUtils.bytesToHex(bytes);
                            handler.sendMessage(message);
                        }
                    }
                }
                if (mUsbDeviceConnection != null) {
                    mUsbDeviceConnection.close();
                    mUsbDeviceConnection = null;
                }
            }
        });
        mReadingthread.start();
        showToast("读取数据");
    }


    private void showConfirmPop() {
        View laheiView = LayoutInflater.from(this).inflate(R.layout.pop_udun_confirm, null);
        TextView textView = laheiView.findViewById(R.id.tv_info);
        textView.setText("点击U盾上的“确认”，即表示您同意");
        UIUtils.appendText(textView, "服务条款", "#1D89E4");

        textView.setOnClickListener(view -> {
            showBackupTips();
        });

        dialog = new Dialog(this, R.style.Dialog);
        dialog.setContentView(laheiView);
        dialog.setCancelable(false);
        dialog.show();
    }


    /**
     * 用UsbDeviceConnection与UsbInterface进行端点设置和通讯
     */
    private void getEndPoint(UsbDeviceConnection connection, UsbInterface usbInterface) {
        if (usbInterface.getEndpoint(0) != null) {
            usbEndpointIn = usbInterface.getEndpoint(0);
        }
        if (usbInterface.getEndpoint(1) != null) {
            usbEndpointOut = usbInterface.getEndpoint(1);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        release();
        if (mUsbReceiver != null) {
            unregisterReceiver(mUsbReceiver);
        }
    }

    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
//            if(!isTargetDevice(device)){
//                return
//            }
            if (BeemIntent.ACTION_USB_INTENT.equals(action)) {
                synchronized (this) {
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
                            && mUsbDevice.equals(device)) {
                        //TODO 授权成功，操作USB设备
                        ToastUtils.ShowToast(ConnectActivity.this, "usb授权成功");
                       /* runOnUiThread(() -> {
                            if (usbManager.hasPermission(mUsbDevice)) {
                                findIntfAndEpt();
                            }
                        });*/
                    } else {
                        //用户点击拒绝了
                        ToastUtils.ShowToast(ConnectActivity.this, "拒绝usb授权");
                    }
                }
            } else if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
                showToast("插入设备");
                Log.d("dj", "==========插入设备");
                //插入usb
                onLoading();

            } else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
                showToast("拔出设备");
                //拔出usb
                release();
//                onLoading();
            }

        }
    };

    private void release() {
        if (dialog != null && dialog.isShowing()) {
            dialog.dismiss();
            dialog = null;
        }
        if (mReadingthread != null) {
            isReading = false;
            mReadingthread.stop();
            mReadingthread = null;
        }
        if (mUsbDeviceConnection != null) {
            mUsbDeviceConnection.releaseInterface(mUsbInterface);
            mUsbDeviceConnection.close();
            mUsbDeviceConnection = null;
        }
    }
}
